Skip to content

Conversation

@Fabcien
Copy link

@Fabcien Fabcien commented Feb 9, 2026

Cashtab will still be called via a redirection if no app handles the link first. This makes this code compatible with both mobile and desktop with no special case.

Works together with PayButton/paybutton-server#1106.

Summary by CodeRabbit

  • New Features
    • Added deeplink support for XEC payments, enabling seamless browser-to-payment-app flow for enhanced transaction processing.
    • Deeplink generation now uses the configured API base URL by default, ensuring consistent payment routing without extra setup.

Cashtab will still be called via a redirection if no app handles the link first. This makes this code compatible with both mobile and desktop with no special case.

Works together with PayButton/paybutton-server#1106.
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 9, 2026

📝 Walkthrough

Walkthrough

Adds a BIP21→deeplink conversion and uses it for XEC paybutton clicks: Widget now builds a deeplink from a BIP21 URL and calls the payment opener with both the original URL and the deeplink; WidgetContainer defaults apiBaseUrl from paybutton-config.json.

Changes

Cohort / File(s) Summary
Widget behavior & BIP21 conversion
react/lib/components/Widget/Widget.tsx
Added convertBip21ToDeeplink(bip21Url: string, apiBaseUrl?: string) and updated handleButtonClick for XEC addresses to compute a deeplink and call openCashtabPayment with both the original BIP21 URL and the deeplink.
Configuration defaulting
react/lib/components/Widget/WidgetContainer.tsx, react/.../paybutton-config.json
Imported paybutton-config.json and set apiBaseUrl = config.apiBaseUrl as a default in WidgetContainer props destructuring so apiBaseUrl is taken from config when not provided.

Sequence Diagram

sequenceDiagram
    participant User as User
    participant Widget as Widget Component
    participant Converter as convertBip21ToDeeplink
    participant Cashtab as openCashtabPayment

    User->>Widget: Click PayButton (XEC)
    Widget->>Widget: handleButtonClick(bip21Url)
    Widget->>Converter: convertBip21ToDeeplink(bip21Url, apiBaseUrl)
    Converter-->>Widget: deeplink URL
    Widget->>Cashtab: openCashtabPayment(bip21Url, deeplink)
    Cashtab-->>User: Open payment app / deeplink handled
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested labels

enhancement (behind the scenes)

Suggested reviewers

  • chedieck
  • lissavxo
  • Klakurka

Poem

🐰 I hopped from url to deeplink bright,
A BIP21 turned to payment light,
One click, two links — a tidy feat,
Wallets wake and coins shall meet,
Hooray, the rabbit danced a byte!

🚥 Pre-merge checks | ✅ 2 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is incomplete; it lacks required sections like 'Related to #' issue reference, detailed description, and test plan as specified in the template. Add the issue reference, expand the description section with context and motivation, and provide a comprehensive test plan for the deeplink implementation.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Generate deeplinks instead of calling Cashtab directly' clearly summarizes the main change—switching from direct Cashtab calls to deeplink generation.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into master

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Klakurka Klakurka self-requested a review February 9, 2026 21:01
@Klakurka Klakurka added the enhancement (UI/UX/feature) New feature or request label Feb 9, 2026
@Klakurka Klakurka requested review from chedieck and removed request for Klakurka February 11, 2026 21:51
Copy link
Collaborator

@chedieck chedieck left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hardcoded URL wasn't letting me test locally, so I submitted a commit to fix it.

When testing, after clicking the button I am being correctly redirected to
http://localhost:3000/app?address=ecash%3Aqr64gaal5zx97judme7nmqxpru6gnx8p3uwgvx585h&amount=5&op_return_raw=045041590000001033ab8ab542994e158c6b0c0ddb6ea127&b=1

which is running PayButton/paybutton-server#1106, so I should get redirected to:
https://cashtab.com/#/send?bip21=ecash:qr64gaal5zx97judme7nmqxpru6gnx8p3uwgvx585h?amount=5&op_return_raw=045041590000001033ab8ab542994e158c6b0c0ddb6ea127

... which appears correctly in my logs, as the URL I'll be redirected to.

Nonetheless, I get a flashing error:

Image

... and redirected to the server's dashboard.

params.set('b', '1')

// Return absolute URL for the deeplink
return `https://paybutton.org/app?${params.toString()}`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should not have the domain hardcoded, we have apiBaseUrl

And move the  conversion function outside of the component to make the rabbit happy.
@Fabcien
Copy link
Author

Fabcien commented Feb 12, 2026

I added a commit with the requested fix and the Rabbit suggestion

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@react/lib/components/Widget/WidgetContainer.tsx`:
- Line 5: The import at the top of WidgetContainer.tsx currently references a
non-existent module (import config from '../../paybutton-config.json'); change
this to import the existing config (import config from
'../../example-config.json') so the WidgetContainer component can access the
required apiBaseUrl via the config object.

import { getAltpaymentClient } from '../../altpayment';
import { GlobalStyles } from '@mui/material'

import config from '../../paybutton-config.json'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check that the config file exists and inspect its contents
fd 'paybutton-config.json' --type f
if fd 'paybutton-config.json' --type f > /dev/null 2>&1; then
  echo "=== File contents ==="
  fd 'paybutton-config.json' --type f --exec cat {}
else
  echo "File not found"
fi

Repository: PayButton/paybutton

Length of output: 84


🏁 Script executed:

#!/bin/bash
# Search for any config-related files
echo "=== Config files in repo ==="
fd -e json --type f | grep -i config | head -20

echo ""
echo "=== Search for paybutton-config references ==="
rg 'paybutton-config' --type ts --type tsx

echo ""
echo "=== Search for apiBaseUrl references ==="
rg 'apiBaseUrl' --type ts --type tsx -A 2 -B 2

Repository: PayButton/paybutton

Length of output: 379


🏁 Script executed:

#!/bin/bash
# Check the WidgetContainer file for the config usage
echo "=== WidgetContainer.tsx (first 130 lines) ==="
head -130 "react/lib/components/Widget/WidgetContainer.tsx" | tail -50

echo ""
echo "=== example-config.json ==="
cat "react/lib/example-config.json"

echo ""
echo "=== All files in react/lib ==="
fd --type f --max-depth 1 '' "react/lib"

Repository: PayButton/paybutton

Length of output: 1924


Change the import to reference example-config.json instead of the non-existent paybutton-config.json.

The file paybutton-config.json does not exist in the repository. The correct config file is react/lib/example-config.json, which contains the required apiBaseUrl property. Update the import path from import config from '../../paybutton-config.json' to import config from '../../example-config.json'.

🤖 Prompt for AI Agents
In `@react/lib/components/Widget/WidgetContainer.tsx` at line 5, The import at the
top of WidgetContainer.tsx currently references a non-existent module (import
config from '../../paybutton-config.json'); change this to import the existing
config (import config from '../../example-config.json') so the WidgetContainer
component can access the required apiBaseUrl via the config object.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement (UI/UX/feature) New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants